//************************************************************************
//
// Exporter.cpp
//
//************************************************************************

#include "StdAfx.h"
#include "Exporter.h"

//////////////////////////////////////////////////////////////////////////
// implementations of different exporters

class CExporterXML : public CExporter
{
public:
    CExporterXML(void);

    virtual void BeginExport(void);
    virtual void ExportURB(CURB *pURB);
    virtual void EndExport(void);

public:
    virtual void OutputLine(LPCTSTR sLine);

protected:
    void IncreaseIndent(void);
    void DecreaseIndent(void);
    void OutputTag(LPCTSTR sTag, LPCTSTR sFormat, ...);

protected:
    int m_nIndent;
};

CExporterXML::CExporterXML(void)
{
    m_sFilename = "SnoopyProExport.xml";
    m_nIndent = 0;
}

void CExporterXML::BeginExport(void)
{
    OutputFormat(_T("<?xml version='1.0'?>"));
    OutputFormat(_T("<!-- This file was generated by SnoopyPro -->"));
    OutputFormat(_T("<snoopyprolog>"));
    IncreaseIndent();
}

void CExporterXML::ExportURB(CURB *pURB)
{
    LPTSTR sBuffer = (LPTSTR) alloca((2 * MAX_USB_TRANSFERBUFFER_SIZE + 1) * sizeof(TCHAR));
    OutputFormat(_T("<urb sequence=\"%d\">"), pURB->GetSequenceNr());
    IncreaseIndent();
    OutputTag(_T("function"), pURB->GetFunctionStr());
    OutputTag(_T("timestamp"), _T("%d"), pURB->GetTime(m_pAR));
    OutputTag(_T("endpoint"), _T("%d"), pURB->GetEndpoint());
    if(pURB->GetPayloadCount(-1) > 0)
    {
        OutputTag(_T("packetcount"), _T("%d"), pURB->GetPacketCount());
        for(int nPacket = 0 ; nPacket < pURB->GetPacketCount(); ++nPacket)
        {
            OutputFormat(_T("<payload packet=\"%d\">"), nPacket);
            IncreaseIndent();
            OutputTag(_T("payloadcount"), _T("%d"), pURB->GetPayloadCount(nPacket));
            OutputTag(_T("payloadbytes"), pURB->GetPayloadXML(nPacket, sBuffer));
            DecreaseIndent();
            OutputFormat(_T("</payload>"));
        }
    }
    DecreaseIndent();
    OutputFormat(_T("</urb>"));
}

void CExporterXML::EndExport(void)
{
    DecreaseIndent();
    OutputFormat(_T("</snoopyprolog>"));
}

void CExporterXML::OutputLine(LPCTSTR sLine)
{
    static TCHAR spaces[] = _T("                                            "
        "                                                                ");
    spaces[m_nIndent] = '\0';
    CExporter::OutputLine(spaces);
    spaces[m_nIndent] = ' ';
    CExporter::OutputLine(sLine);
}

void CExporterXML::IncreaseIndent(void)
{
    m_nIndent = min(m_nIndent + 4, 40);
}

void CExporterXML::DecreaseIndent(void)
{
    m_nIndent = max(m_nIndent - 4,  0);
}

void CExporterXML::OutputTag(LPCTSTR sTag, LPCTSTR sFormat, ...)
{
    va_list params;
    va_start(params, sFormat);
    TCHAR sLine[4096];
#ifdef UNICODE
	vswprintf(sLine, sFormat, params);
#else
	vsprintf(sLine, sFormat, params);
#endif
	va_end(params);
    OutputFormat(_T("<%s>%s</%s>"), sTag, sLine, sTag);
}

//////////////////////////////////////////////////////////////////////////
// CExporter

CExporter::CExporter(void)
{
    m_sFilename = "SnoopyProExport.log";
}

CExporter::~CExporter(void)
{
}

CExporter* CExporter::Factory(EXPORTER_TYPE ExporterType)
{
    switch(ExporterType)
    {
    case EXPTYPE_XML:
        return new CExporterXML();
        
    case EXPTYPE_PLAIN_CONDENSED:
    case EXPTYPE_PLAIN_FULL:
    case EXPTYPE_CUSTOM:
    default:
        TRACE("CExporter::Factory(%d): unknown exporter type!\n",
            ExporterType);
        break;
    }
    return NULL;
}

void CExporter::SetOutputFilename(LPCTSTR sFilename)
{
    m_sFilename = sFilename;
}

void CExporter::SetArrayURB(CArrayURB *pAR)
{
    m_pAR = pAR;
}

void CExporter::Export(void)
{
    int nFileMode = CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyWrite;
    if(m_File.Open(m_sFilename, nFileMode))
    {
        // iterate over the urbs of the urbarray and export each
        BeginExport();
        for(int nURB = 0; nURB < m_pAR->GetSize(); ++nURB)
        {
            ExportURB(m_pAR->GetAt(nURB));
        }
        EndExport();
        m_File.Flush();
        TRACE("Wrote to %s\n", m_File.GetFilePath());
        m_File.Close();
    }
}

void CExporter::OutputLine(LPCTSTR sLine)
{
    m_File.Write(sLine, _tcslen(sLine) * sizeof(TCHAR));
    const TCHAR CRLF[] = _T("\r\n");
    m_File.Write(CRLF, _tcslen(CRLF) * sizeof(TCHAR));
}

void CExporter::OutputFormat(LPCTSTR sFormat, ...)
{
    va_list params;
    va_start(params, sFormat);
    TCHAR sLine[4096];
#ifdef UNICODE
	vswprintf(sLine, sFormat, params);
#else
	vsprintf(sLine, sFormat, params);
#endif
	va_end(params);
    OutputLine(sLine);
}

void CExporter::BeginExport(void)
{
}

void CExporter::ExportURB(CURB *pURB)
{
    OutputFormat(_T("exporting %x"), pURB);
}

void CExporter::EndExport(void)
{
}

//** end of Exporter.cpp *************************************************
/*************************************************************************

  $Log: /CD/Entertainment/Tools/Snoopy/SnoopyPro/Exporter.cpp $
 * 
 * 2     10/07/02 2:51p Rbosa
 * 
 * 1     10/07/02 12:42p Rbosa
  Revision 1.1  2002/10/05 01:10:43  rbosa
  Added the basic framework for exporting a log into an XML file. The
  output written is fairly poor. This checkin is mainly to get the
  framework in place and get feedback on it.


*************************************************************************/